﻿using MCUPackage;
using MCUPackage.Utils;
using System;
using System.Collections.Generic;
using System.Text;

namespace SxPackages.STC32G
{
	/// <summary>
	/// 工程文件模板工具类
	/// </summary>
	static class PrjTemplate
	{
		/// <summary>
		/// 文件选项模板, 2表示默认, 1表示选中, 提供三个设置项
		/// AlwaysBuild: 总是编译, 用于ProjectConfig.c
		/// GenerateAssemblyFile, AssembleAssemblyFile用于FreeRTOS系统的port.c文件
		/// uRentF reentrant选项, 2默认, 0为取消, STC32G_PutChar.c使用
		/// </summary>
		private const string FILE_OPTION =
@"
              <FileOption>
                <CommonProperty>
                  <UseCPPCompiler>2</UseCPPCompiler>
                  <RVCTCodeConst>0</RVCTCodeConst>
                  <RVCTZI>0</RVCTZI>
                  <RVCTOtherData>0</RVCTOtherData>
                  <ModuleSelection>0</ModuleSelection>
                  <IncludeInBuild>2</IncludeInBuild>
                  <AlwaysBuild>{0}</AlwaysBuild>
                  <GenerateAssemblyFile>{1}</GenerateAssemblyFile>
                  <AssembleAssemblyFile>{2}</AssembleAssemblyFile>
                  <PublicsOnly>2</PublicsOnly>
                  <StopOnExitCode>11</StopOnExitCode>
                  <CustomArgument></CustomArgument>
                  <IncludeLibraryModules></IncludeLibraryModules>
                  <ComprImg>1</ComprImg>
                  <BankNo>65535</BankNo>
                </CommonProperty>
                <File251>
                  <C251>
                    <RegColor>2</RegColor>
                    <uOrder>2</uOrder>
                    <uAlias>2</uAlias>
                    <uRentF>{3}</uRentF>
                    <uUch>2</uUch>
                    <uFlt64>2</uFlt64>
                    <Fuzzy>8</Fuzzy>
                    <Optim>10</Optim>
                    <wLevel>4</wLevel>
                    <SizSpd>2</SizSpd>
                    <AcaOpt>2</AcaOpt>
                    <VariousControls>
                      <MiscControls></MiscControls>
                      <Define></Define>
                      <Undefine></Undefine>
                      <IncludePath></IncludePath>
                    </VariousControls>
                  </C251>
                </File251>
              </FileOption>";

		/// <summary>
		/// 文件组模板
		/// </summary>
		private const string GRP_TEMPLATE =
@"        <Group>
          <GroupName>{0}</GroupName>
          <Files>{1}
          </Files>
        </Group>";

		/// <summary>
		/// 文件模板 c文件类型为1, 头文件以及txt文件为5, 类库为4
		/// </summary>
		private const string FILE_TEMPLATE =
@"            <File>
              <FileName>{0}</FileName>
              <FileType>{1}</FileType>
              <FilePath>{2}</FilePath>{3}
            </File>";

		/// <summary>
		/// 要显示在工程中的文件集合
		/// </summary>
		private static Dictionary<PrjPathTypes, List<string>> mFiles = new Dictionary<PrjPathTypes, List<string>>();

		/// <summary>
		/// 初始化, 每次创建项目时都要初始化一次
		/// </summary>
		public static void Init()
		{
			mFiles.Clear();
		}

		/// <summary>
		/// 追加文件
		/// </summary>
		/// <param name="aType"></param>
		/// <param name="aFile"></param>
		public static void Append(PrjPathTypes aType, string aFile)
		{
			if (!mFiles.ContainsKey(aType))
			{
				mFiles[aType] = new List<string>();
			}
			mFiles[aType].Add(aFile);
		}

		/// <summary>
		/// 组成工程组的类型
		/// </summary>
		private static readonly PrjPathTypes[] PRJ_TYPES = new PrjPathTypes[]
				{ PrjPathTypes.Inc, PrjPathTypes.Src, PrjPathTypes.Middlewares_ZnFat, PrjPathTypes.Middlewares_FreeRTOS,
				 PrjPathTypes.Drivers_STC32_Src, PrjPathTypes.Drivers_STC32_Libs, PrjPathTypes.Doc};
		/// <summary>
		/// 工程组名集合
		/// </summary>
		private static readonly string[] PRJ_GROUPS = new string[]
			{"Usr/Inc", "Usr/Src", "Middlewares/ZnFat", "Middlewares/FreeRTOS", "Drivers/STC32", "Libs", "Doc"};

		/// <summary>
		/// 创建工程文件
		/// </summary>
		/// <param name="aPath"></param>
		public static bool Create(string aPath, STC32GQFP64 aOptions)
		{
			if (mFiles.Count < 1)
			{
				return false;
			}

			StringBuilder grpSb = new StringBuilder();
			for (int i = 0; i < PRJ_TYPES.Length; i++)
			{
				var type = PRJ_TYPES[i];
				if (mFiles.ContainsKey(type))
				{
					// 创建分组
					var files = mFiles[type];
					StringBuilder fileSb = new StringBuilder();
					foreach (var file in files)
					{
						int fileType = 5;
						if (file.EndsWith(".c", StringComparison.CurrentCultureIgnoreCase))
						{
							fileType = 1;
						}
						else if (file.EndsWith(".lib", StringComparison.CurrentCultureIgnoreCase))
						{
							fileType = 4;
						}
						string path = string.Format("../{0}/{1}", type.ToDescription(), file);
						// 特殊配置
						string opt = string.Empty;
						if (type == PrjPathTypes.Src && file.Equals("ProjectConfig.c", StringComparison.CurrentCultureIgnoreCase))
						{
							// 项目配置文件
							opt = string.Format(FILE_OPTION, 1, 2, 2, 2);
						}
						else if (type == PrjPathTypes.Middlewares_FreeRTOS && file.Equals("port.c", StringComparison.CurrentCultureIgnoreCase))
						{
							// FreeRTOS文件
							opt = string.Format(FILE_OPTION, 2, 1, 1, 2);
						}
						else if (type == PrjPathTypes.Drivers_STC32_Src && file.Equals("STC32G_PutChar.c", StringComparison.CurrentCultureIgnoreCase))
						{
							opt = string.Format(FILE_OPTION, 2, 2, 2, 0);
						}
						fileSb.AppendLine();
						fileSb.AppendFormat(FILE_TEMPLATE, file, fileType, path, opt);
					}
					grpSb.AppendLine();
					grpSb.AppendFormat(GRP_TEMPLATE, PRJ_GROUPS[i], fileSb.ToString());
				}
			}

			string src = PrjPathTypes.MDK.ToFilePath(aOptions.TemplatePath, "Template.uvproj");
			string dst = PrjPathTypes.MDK.ToFilePath(aPath, $"{aOptions.Project.Name}.uvproj");
			var pairs = TemplateHelper.CreatePairs();

			pairs["ProjectName"] = aOptions.Project.Name;
			pairs["Freq"] = Convert.ToString((int)(aOptions.mSYSTEM.FreqValue * 1000));
			pairs["Reentrant"] = aOptions.mFreeRTOS.Enable ? "1" : "0";
			pairs["Groups"] = grpSb.ToString();

			return aOptions.CreateByTemplate(src, dst, pairs);
		}
	}
}
